package org.sidora.core.context;

import com.db4o.ObjectContainer;
import com.db4o.query.Predicate;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.sidora.core.KeyObject;
import org.sidora.core.util.AbstractFactory;
import org.sidora.core.util.AbstractInventory;
import org.sidora.core.util.OCProvider;
import org.sidora.core.util.ParameterCollector;

/**
 * StratigraphicRelation
 * @author Enric Tartera, Juan Manuel Gimeno, Roger Masgoret
 * @version 1.0
 */
public class StratigraphicRelation {
    private Context a;
    private Context b;
    
    
    /** Creates a new instance of StratigraphicRelation */
    protected StratigraphicRelation() {
    }
    
    public boolean hasContext(Context context){
        return ((a==context ) || (b==context));
    }
    
    public static class Inventory extends AbstractInventory{
        public Object getNewObject(ParameterCollector param) throws RuntimeException {
            String type = (String) param.get("type");
            Context contextA = (Context) param.get("contextA");
            Context contextB = (Context) param.get("contextB");
            StratigraphicRelation relation;
            
            
            if (type == "equality"){
                relation = new Equality();
            }else if(type == "equivalence"){
                relation = new Equivalence();
            }else if(type == "succesion"){
                relation = new Succesion();
            }else{
                throw new RuntimeException();
            }
            
            relation.setA(contextA);
            relation.setB(contextB);
            
            return relation;
        }
        
        protected KeyObject getNewKey(ParameterCollector param) {
            return null;
        }
        
        public Object getObject(ParameterCollector param) {
            return null;
        }
        
        public static List<Equality> getEqualTo(final Context context){
            ObjectContainer db = OCProvider.getInstance();
            List<Equality> list = db.query(new Predicate<Equality>(){
                
                @Override
                public boolean match(Equality equality) {
                    
                    return equality.hasContext(context);
                }});
                
                return list;
        }
        
        
        public static List<Equivalence> getEquivalentTo(final Context context){
            ObjectContainer db = OCProvider.getInstance();
            List<Equivalence> list = db.query(new Predicate<Equivalence>(){
                
                @Override
                public boolean match(Equivalence equivalence) {
                    
                    return equivalence.hasContext(context);
                }});
                
                return list;
        }
        
        
        public static List<Succesion> getPreviousTo(final Context context){
            ObjectContainer db = OCProvider.getInstance();
            List<Succesion> list = db.query(new Predicate<Succesion>(){
                
                @Override
                public boolean match(Succesion succesion) {
                    
                    return succesion.isPrevious(context);
                }});
                
                return list;
        }
        
        
        public static List<Succesion> getNextTo(final Context context){
            ObjectContainer db = OCProvider.getInstance();
            List<Succesion> list = db.query(new Predicate<Succesion>(){
                
                @Override
                public boolean match(Succesion succesion) {
                    
                    return succesion.isNext(context);
                }});
                
                return list;
        }
        
        public static List<StratigraphicRelation> getList(){
            ObjectContainer db = OCProvider.getInstance();
            List<StratigraphicRelation> list = db.query(StratigraphicRelation.class);
            db.commit();
            return list;
        }
        
        public boolean hasEquality(Context ca, Context cb){
            String str = "";
            Equality equ;
            List<Equality> equals = StratigraphicRelation.Inventory.getEqualTo(ca);
            
            Iterator<Equality> iter2 = equals.iterator();
            
            while (iter2.hasNext()){
                equ = (Equality)iter2.next();
                
                if (equ.hasContext(cb)){
                    return true;
                }
            }
            return false;
        }
        
        public boolean hasEquivalence(Context ca, Context cb){
            String str = "";
            Equivalence equ;
            List<Equivalence> equals = StratigraphicRelation.Inventory.getEquivalentTo(ca);
            
            Iterator<Equivalence> iter2 = equals.iterator();
            
            while (iter2.hasNext()){
                equ = (Equivalence)iter2.next();
                
                if (equ.hasContext(cb)){
                    return true;
                }
            }
            return false;
        }
        
        public boolean hasNextTo(Context ca, Context cb){
            String str = "";
            Succesion suc;
            List<Succesion> sucs = StratigraphicRelation.Inventory.getNextTo(ca);
            
            Iterator<Succesion> iter2 = sucs.iterator();
            
            while (iter2.hasNext()){
                suc = (Succesion)iter2.next();
                
                if (suc.hasContext(cb)){
                    return suc.isNext(cb);
                }
            }
            return false;
        }
        
        public boolean hasPreviousTo(Context ca, Context cb){
            String str = "";
            Succesion suc;
            List<Succesion> sucs = StratigraphicRelation.Inventory.getPreviousTo(ca);
            
            Iterator<Succesion> iter2 = sucs.iterator();
            
            while (iter2.hasNext()){
                suc = (Succesion)iter2.next();
                
                if (suc.hasContext(cb)){
                    return suc.isPrevious(cb);
                }
            }
            return false;
        }
        
        public static void updatePrevious(Context context, List<Context> list){
            StratigraphicRelation.Inventory sri = new StratigraphicRelation.Inventory();
            List<Succesion> listSuccesion;
            Set<Context> contextsToAdd = new TreeSet<Context>();
            
            listSuccesion = StratigraphicRelation.Inventory.getPreviousTo(context);
            
            contextsToAdd.addAll(list);
            
            //Obtenim les llistes a afegir o borrar reaprofitant la llista list
            Iterator iterSuccesion = listSuccesion.iterator();
            while (iterSuccesion.hasNext()){
                Succesion Succesion = (Succesion)iterSuccesion.next();
                Context acontext = Succesion.getOtherContext(context);
                
                if (list.contains(acontext)){
                    contextsToAdd.remove(acontext);
                } else {
                    AbstractInventory.deleteObject(Succesion);
                }
            }
            
            //Creem les Succesions
            Iterator iterAdd = contextsToAdd.iterator();
            while (iterAdd.hasNext()){
                ParameterCollector param = new ParameterCollector();
                param.put("type","succesion");
                param.put("contextA", context);
                param.put("contextB",(Context)iterAdd.next());
                
                Succesion equ = (Succesion)sri.getNewObject(param);
                AbstractInventory.setObject(equ);
            }
        }
        
        public static void updateNextTo(Context context, List<Context> list){
            StratigraphicRelation.Inventory sri = new StratigraphicRelation.Inventory();
            List<Succesion> listSuccesion;
            Set<Context> contextsToAdd = new TreeSet<Context>();
            
            listSuccesion = StratigraphicRelation.Inventory.getNextTo(context);
            
            contextsToAdd.addAll(list);
            
            //Obtenim les llistes a afegir o borrar reaprofitant la llista list
            Iterator iterSuccesion = listSuccesion.iterator();
            while (iterSuccesion.hasNext()){
                Succesion Succesion = (Succesion)iterSuccesion.next();
                Context acontext = Succesion.getOtherContext(context);
                
                if (list.contains(acontext)){
                    contextsToAdd.remove(acontext);
                } else {
                    AbstractInventory.deleteObject(Succesion);
                }
            }
            
            //Creem les Succesions
            Iterator iterAdd = contextsToAdd.iterator();
            while (iterAdd.hasNext()){
                ParameterCollector param = new ParameterCollector();
                param.put("type","succesion");
                param.put("contextB", context);
                param.put("contextA",(Context)iterAdd.next());
                
                Succesion equ = (Succesion)sri.getNewObject(param);
                AbstractInventory.setObject(equ);
            }
        }
        
        public static void updateEquivalence(Context context, List<Context> list){
            StratigraphicRelation.Inventory sri = new StratigraphicRelation.Inventory();
            List<Equivalence> listEquivalence;
            Set<Context> contextsToAdd = new TreeSet<Context>();
            
            listEquivalence = StratigraphicRelation.Inventory.getEquivalentTo(context);
            
            contextsToAdd.addAll(list);
            
            //Obtenim les llistes a afegir o borrar reaprofitant la llista list
            Iterator iterEquivalence = listEquivalence.iterator();
            while (iterEquivalence.hasNext()){
                Equivalence Equivalence = (Equivalence)iterEquivalence.next();
                Context acontext = Equivalence.getOtherContext(context);
                
                if (list.contains(acontext)){
                    contextsToAdd.remove(acontext);
                } else {
                    AbstractInventory.deleteObject(Equivalence);
                }
            }
            
            //Creem les Equivalences
            Iterator iterAdd = contextsToAdd.iterator();
            while (iterAdd.hasNext()){
                ParameterCollector param = new ParameterCollector();
                param.put("type","equivalence");
                param.put("contextA", context);
                param.put("contextB",(Context)iterAdd.next());
                
                Equivalence equ = (Equivalence)sri.getNewObject(param);
                AbstractInventory.setObject(equ);
            }
        }
        
        public static void updateEquality(Context context, List<Context> list){
            StratigraphicRelation.Inventory sri = new StratigraphicRelation.Inventory();
            List<Equality> listEquality;
            Set<Context> contextsToAdd = new TreeSet<Context>();
            
            listEquality = StratigraphicRelation.Inventory.getEqualTo(context);
            
            contextsToAdd.addAll(list);
            
            //Obtenim les llistes a afegir o borrar reaprofitant la llista list
            Iterator iterEquality = listEquality.iterator();
            while (iterEquality.hasNext()){
                Equality equality = (Equality)iterEquality.next();
                Context acontext = equality.getOtherContext(context);
                
                if (list.contains(acontext)){
                    contextsToAdd.remove(acontext);
                } else {
                    AbstractInventory.deleteObject(equality);
                }
            }
            
            //Creem les equalitys
            Iterator iterAdd = contextsToAdd.iterator();
            while (iterAdd.hasNext()){
                ParameterCollector param = new ParameterCollector();
                param.put("type","equality");
                param.put("contextA", context);
                param.put("contextB",(Context)iterAdd.next());
                
                Equality equ = (Equality)sri.getNewObject(param);
                AbstractInventory.setObject(equ);
            }
        }
    }
    
    
    
    
    public Context getA() {
        return a;
    }
    
    public void setA(Context a) {
        this.a = a;
    }
    
    public Context getB() {
        return b;
    }
    
    public void setB(Context b) {
        this.b = b;
    }
    
    public Context getOtherContext(Context con){
        if (this.a == con){
            return b;
        }else{
            return a;
        }
    }
    
    
    
    
}


//
//public class Equality extends StratigraphicRelation{
//
//        /** Creates a new instance of Equality */
//        public Equality() {
//        }
//
//    }
//
//    public class Equivalence extends StratigraphicRelation{
//
//        /**
//         * Creates a new instance of Equivalence
//         */
//        public Equivalence() {
//        }
//
//    }
//
//    public class Succesion extends StratigraphicRelation{
//
//        /** Creates a new instance of Succesion */
//        public Succesion() {
//        }
//
//    }
